/*
 *  Copyright (C) 2010 Takaji
 * 
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 * 
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 * 
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/*
 * TransactionManagerNewView.java
 *
 * Created on Jan 2, 2010, 1:18:32 PM
 */
package dakside.hacc.modules.transactions.trxman;

import dakside.hacc.core.models.Currency;
import dakside.hacc.core.models.Transaction;
import dakside.hacc.core.models.TransactionType;
import org.dakside.duck.helpers.SwingHelper;
import org.dakside.utils.FinancialHelper;
import org.dakside.utils.ResourceCentre;
import java.awt.Component;
import java.util.HashMap;
import java.util.logging.Logger;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import org.dakside.duck.plugins.AppCentral;
import org.dakside.duck.plugins.AppCentralAPI;
import org.dakside.duck.plugins.AppConstants;
import org.dakside.duck.plugins.Command;
import org.dakside.duck.plugins.DefaultCommandInvoker;
import org.dakside.duck.plugins.ToolbarContainer;

/**
 *
 * @author Takaji
 */
public class TransactionManageView extends javax.swing.JPanel implements ToolbarContainer {

    private static final Logger logger = Logger.getLogger(TransactionManageView.class.getName());
    private final ResourceCentre rc = ResourceCentre.getInstance(this);
    private AppCentralAPI api = AppCentral.getAPIDelegate();

    /** Creates new form TransactionManagerNewView */
    public TransactionManageView() {
        initComponents();
        transactionTable1.getSelectionModel().addListSelectionListener(new ListSelectionListener() {

            public void valueChanged(ListSelectionEvent e) {
                if (transactionTable1.getModel() == null) {
                    return;
                }

                Transaction[] trx = transactionTable1.getSelectedTransactions();
//                logger.info("Selected = " + trx.length);
                if (trx == null) {
                    //dont care
                } else if (trx.length == 1) {
                    transactionDetailPanel1.setTransaction(trx[0]);
                } else {
                    transactionDetailPanel1.setTransaction(null);
                }

                //show summary
                showSummary(trx);

                getInvoker().setEnabled(AppConstants.Commands.DELETE, trx.length > 0);
            }

            private void showSummary(Transaction[] transactions) {
                if (transactions == null || transactions.length == 0) {
                    api.setStatusMessage("");
                } else {
                    //calculate summary
                    HashMap<Currency, Double> sum = new HashMap<Currency, Double>();
                    for (Transaction transaction : transactions) {
                        if (transaction == null || transaction.getCurrency() == null) {
                            continue; //ignore broken records
                        }
                        if (!sum.containsKey(transaction.getCurrency())) {
                            sum.put(transaction.getCurrency(), transaction.getAmount());
//                            logger.info(sum.get(transaction.getCurrency()).toString());
                        } else {
                            sum.put(transaction.getCurrency(), sum.get(transaction.getCurrency()) + transaction.getAmount());
//                            logger.info(sum.get(transaction.getCurrency()).toString());
                        }
                    }

                    StringBuilder temp = new StringBuilder();
                    for (Currency c : sum.keySet()) {
                        temp.append(FinancialHelper.formatCurrency(sum.get(c)) + " " + c + " ");
                    }
                    api.setStatusMessage(temp.toString());
                }
            }
        });
        refresh();
        //on startup
        //hide the details panel
        showHideDetailPanel(false);
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        customToolbar = new javax.swing.JToolBar();
        btnHideDetails = new javax.swing.JButton();
        jSeparator2 = new javax.swing.JToolBar.Separator();
        btnExportCSV = new javax.swing.JButton();
        transactionDetailPanel1 = new dakside.hacc.modules.transactions.trxman.TransactionDetailPanel();
        jScrollPane1 = new javax.swing.JScrollPane();
        transactionTable1 = new dakside.hacc.modules.transactions.trxman.TransactionTable();
        jToolBar2 = new javax.swing.JToolBar();
        jLabel1 = new javax.swing.JLabel();
        comboTransactionType = new javax.swing.JComboBox();
        jLabel2 = new javax.swing.JLabel();
        comboPosting = new javax.swing.JComboBox();
        jLabel3 = new javax.swing.JLabel();
        dateFrom = new com.toedter.calendar.JDateChooser();
        jLabel4 = new javax.swing.JLabel();
        dateTo = new com.toedter.calendar.JDateChooser();
        btnClear = new javax.swing.JButton();

        customToolbar.setFloatable(false);
        customToolbar.setRollover(true);
        customToolbar.setName("customToolbar"); // NOI18N

        btnHideDetails.setText("Hide details panel");
        btnHideDetails.setFocusable(false);
        btnHideDetails.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        btnHideDetails.setName("btnHideDetails"); // NOI18N
        btnHideDetails.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        btnHideDetails.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnHideDetailsActionPerformed(evt);
            }
        });
        customToolbar.add(btnHideDetails);

        jSeparator2.setName("jSeparator2"); // NOI18N
        customToolbar.add(jSeparator2);

        btnExportCSV.setText("Export to CSV");
        btnExportCSV.setFocusable(false);
        btnExportCSV.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        btnExportCSV.setName("btnExportCSV"); // NOI18N
        btnExportCSV.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        btnExportCSV.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnExportCSVActionPerformed(evt);
            }
        });
        customToolbar.add(btnExportCSV);

        transactionDetailPanel1.setName("transactionDetailPanel1"); // NOI18N

        jScrollPane1.setName("jScrollPane1"); // NOI18N

        transactionTable1.setModel(new TransactionTableModel());
        transactionTable1.setName("transactionTable1"); // NOI18N
        transactionTable1.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                transactionTable1MouseClicked(evt);
            }
        });
        transactionTable1.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
            public void propertyChange(java.beans.PropertyChangeEvent evt) {
                transactionTable1PropertyChange(evt);
            }
        });
        jScrollPane1.setViewportView(transactionTable1);

        jToolBar2.setFloatable(false);
        jToolBar2.setRollover(true);
        jToolBar2.setName("jToolBar2"); // NOI18N

        jLabel1.setText("Type");
        jLabel1.setName("jLabel1"); // NOI18N
        jToolBar2.add(jLabel1);

        comboTransactionType.setName("comboTransactionType"); // NOI18N
        comboTransactionType.addItemListener(new java.awt.event.ItemListener() {
            public void itemStateChanged(java.awt.event.ItemEvent evt) {
                comboTransactionTypeItemStateChanged(evt);
            }
        });
        jToolBar2.add(comboTransactionType);

        jLabel2.setText("Status");
        jLabel2.setName("jLabel2"); // NOI18N
        jToolBar2.add(jLabel2);

        comboPosting.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Posted", "Not Posted", "All" }));
        comboPosting.setSelectedIndex(2);
        comboPosting.setName("comboPosting"); // NOI18N
        comboPosting.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                comboPostingActionPerformed(evt);
            }
        });
        jToolBar2.add(comboPosting);

        jLabel3.setText("From");
        jLabel3.setName("jLabel3"); // NOI18N
        jToolBar2.add(jLabel3);

        dateFrom.setName("dateFrom"); // NOI18N
        dateFrom.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
            public void propertyChange(java.beans.PropertyChangeEvent evt) {
                dateFromPropertyChange(evt);
            }
        });
        jToolBar2.add(dateFrom);

        jLabel4.setText("To");
        jLabel4.setName("jLabel4"); // NOI18N
        jToolBar2.add(jLabel4);

        dateTo.setName("dateTo"); // NOI18N
        dateTo.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
            public void propertyChange(java.beans.PropertyChangeEvent evt) {
                dateToPropertyChange(evt);
            }
        });
        jToolBar2.add(dateTo);

        btnClear.setText("Clear");
        btnClear.setFocusable(false);
        btnClear.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        btnClear.setName("btnClear"); // NOI18N
        btnClear.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        btnClear.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnClearActionPerformed(evt);
            }
        });
        jToolBar2.add(btnClear);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jToolBar2, javax.swing.GroupLayout.DEFAULT_SIZE, 563, Short.MAX_VALUE))
            .addComponent(transactionDetailPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, 573, Short.MAX_VALUE)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 553, Short.MAX_VALUE)
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addComponent(jToolBar2, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(transactionDetailPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, 182, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 130, Short.MAX_VALUE)
                .addContainerGap())
        );
    }// </editor-fold>//GEN-END:initComponents

    private void transactionTable1PropertyChange(java.beans.PropertyChangeEvent evt) {//GEN-FIRST:event_transactionTable1PropertyChange
    }//GEN-LAST:event_transactionTable1PropertyChange

    private void btnHideDetailsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnHideDetailsActionPerformed
        showHideDetailPanel();
    }//GEN-LAST:event_btnHideDetailsActionPerformed

    private void save() {
        Transaction trx = transactionDetailPanel1.getTransaction();
        if (trx != null) {
            TransactionManager.getInstance().save(trx);
            //reset detail panel
            //added by Takaji
            transactionDetailPanel1.setTransaction(null);
            //end of change
            loadTransactionTable();
        }
    }

    private void deleteSelection() {
        Transaction[] transactions = transactionTable1.getSelectedTransactions();
        if (transactions == null) {
            //dont care, just ignore
        } else if (!TransactionManager.getInstance().canDelete(transactions)) {
            SwingHelper.alert(rc.getString("cannot_delete"), rc.getString("cannot_delete_header"));
        } else {
            if (TransactionManager.getInstance().delete(transactions)) {
                //reset detail panel
                transactionDetailPanel1.setTransaction(null);
                transactionTable1.removeSelected();
            } else {
                SwingHelper.alert(rc.getString("cannot_delete"), rc.getString("cannot_delete_header"));
            }
        }
    }

    /**
     * Switch transaction details panel state (hide to show and vice versa)
     */
    private void showHideDetailPanel() {
        showHideDetailPanel(!transactionDetailPanel1.isVisible());
    }

    /**
     * Show or hide detail panel
     * @param state true to show panel
     */
    private void showHideDetailPanel(boolean state) {
        transactionDetailPanel1.setVisible(state);
        getInvoker().setEnabled(AppConstants.Commands.SAVE, state);
        //btnDelete.setVisible(state);
        if (state) {
            btnHideDetails.setText(rc.getString("hide_details_panel"));

        } else {
            btnHideDetails.setText(rc.getString("show_details_panel"));
        }
    }

    private void comboTransactionTypeItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_comboTransactionTypeItemStateChanged
        loadTransactionTable();
    }//GEN-LAST:event_comboTransactionTypeItemStateChanged

    private void comboPostingActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_comboPostingActionPerformed
        loadTransactionTable();
    }//GEN-LAST:event_comboPostingActionPerformed

    private void btnExportCSVActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnExportCSVActionPerformed
        Transaction[] transactions = transactionTable1.getTransactions();
        int savedRecords = TransactionManager.getInstance().exportCSV(transactions);
        if (savedRecords < 0) {
            SwingHelper.alert(rc.getString("cantsave"), rc.getString("cantsave_header"));
        } else {
            SwingHelper.alert(rc.getMessage("saved", new Object[]{savedRecords}), rc.getString("saved_header"));
        }
    }//GEN-LAST:event_btnExportCSVActionPerformed

    private void transactionTable1MouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_transactionTable1MouseClicked
        if (evt.getClickCount() >= 2) {
            showHideDetailPanel(true);
        }
    }//GEN-LAST:event_transactionTable1MouseClicked

    private void btnClearActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnClearActionPerformed
        // Clear all filter fields
        //TODO hardcode 
        SwingHelper.comboSelect(comboPosting, "All");
        SwingHelper.comboSelect(comboTransactionType, "All");
        dateFrom.setDate(null);
        dateTo.setDate(null);
    }//GEN-LAST:event_btnClearActionPerformed

    private void dateFromPropertyChange(java.beans.PropertyChangeEvent evt) {//GEN-FIRST:event_dateFromPropertyChange
        // reload transaction table when dateFrom filter changed
        if ("date".equals(evt.getPropertyName())) {
            loadTransactionTable();
        }
    }//GEN-LAST:event_dateFromPropertyChange

    private void dateToPropertyChange(java.beans.PropertyChangeEvent evt) {//GEN-FIRST:event_dateToPropertyChange
        // reload transaction table when dateTo filter changed
        if ("date".equals(evt.getPropertyName())) {
            loadTransactionTable();
        }
    }//GEN-LAST:event_dateToPropertyChange
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton btnClear;
    private javax.swing.JButton btnExportCSV;
    private javax.swing.JButton btnHideDetails;
    private javax.swing.JComboBox comboPosting;
    private javax.swing.JComboBox comboTransactionType;
    private javax.swing.JToolBar customToolbar;
    private com.toedter.calendar.JDateChooser dateFrom;
    private com.toedter.calendar.JDateChooser dateTo;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JToolBar.Separator jSeparator2;
    private javax.swing.JToolBar jToolBar2;
    private dakside.hacc.modules.transactions.trxman.TransactionDetailPanel transactionDetailPanel1;
    private dakside.hacc.modules.transactions.trxman.TransactionTable transactionTable1;
    // End of variables declaration//GEN-END:variables

    /**
     * Refresh and load information from database to view
     */
    private void refresh() {
        transactionDetailPanel1.refresh();
        //load transactions to list
        loadTransactionTable();
        loadTransactionTypeCombobox();
        transactionTable1.format();
    }

    /**
     * Reload transaction table data from database
     */
    private void loadTransactionTable() {
        Boolean isPosted = null;
        TransactionType type = null;
        //transaction type
        if (comboTransactionType.getSelectedItem() instanceof TransactionType) {
            //ignore type
            type = (TransactionType) comboTransactionType.getSelectedItem();
        }
        //TODO hardcode
        //accounting status
        if ("Posted".equals(comboPosting.getSelectedItem())) {
            //ignore type
            isPosted = true;
        } else if ("Not Posted".equals(comboPosting.getSelectedItem())) {
            //ignore type
            isPosted = false;
        } else {
            isPosted = null;
        }
        Transaction[] transactions = TransactionManager.getInstance().getTransactions(type, isPosted, dateFrom.getDate(), dateTo.getDate());
        transactionTable1.load(transactions);
    }

    private void createTransaction() {
        transactionDetailPanel1.setTransaction(null);
    }

    /**
     * Reload transaction type combobox
     */
    private void loadTransactionTypeCombobox() {
        TransactionType[] types = TransactionManager.getInstance().getAllTransactionType();
        Object selectedItem = comboTransactionType.getSelectedItem();
        comboTransactionType.removeAllItems();
        //TODO hardcode
        comboTransactionType.addItem("All"); //default items
        for (TransactionType type : types) {
            comboTransactionType.addItem(type);
        }
        comboTransactionType.setSelectedItem(selectedItem);

        if (comboTransactionType.getSelectedIndex() < 0) {
            comboTransactionType.setSelectedIndex(0);
        }
    }
    //TOOLBAR CONTAINER SUPPORT
    private Component[] toolbar;

    public Component[] getToolbarItems() {
        if (toolbar == null) {
            toolbar = customToolbar.getComponents();
        }
        return toolbar;
    }
    private DefaultCommandInvoker myInvoker = null;

    public final synchronized DefaultCommandInvoker getInvoker() {
        if (myInvoker == null) {
            myInvoker = new DefaultCommandInvoker();
        }
        myInvoker.add(AppConstants.Commands.SAVE, new Command() {

            public Object invoke(Object[] args) {
                save();
                return true;
            }
        });
        myInvoker.add(AppConstants.Commands.REFRESH, new Command() {

            public Object invoke(Object[] args) {
                refresh();
                return true;
            }
        });

        myInvoker.add(AppConstants.Commands.DELETE, new Command() {

            public Object invoke(Object[] args) {
                deleteSelection();
                return true;
            }
        });
        myInvoker.add(AppConstants.Commands.NEW, new Command() {

            public Object invoke(Object[] args) {
                createTransaction();
                showHideDetailPanel(true);
                return true;
            }
        });
        return myInvoker;
    }
    //END OF TOOLBAR CONTAINER SUPPORT
}
